import 'dart:async';

import 'package:async/async.dart';
import 'package:async_test/src/utils.dart';

import '../common/test_page.dart';

class StreamSinkTransformerTestPage extends TestPage {
  StreamSinkTransformerTestPage(super.title) {
    late StreamController controller;
    setUp() {
      controller = StreamController();
    }

    group('StreamSinkTransformer.fromStreamTransformer() .bind()', () {
      test('StreamSinkTransformer.fromStreamTransformer() 转换数据事件', () {
        setUp();
        var transformer = StreamSinkTransformer.fromStreamTransformer(
            StreamTransformer.fromHandlers(handleData: (int i, sink) {
              sink.add(i * 2);
            }));
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen(results.add, onDone: () {
          expect(results);
        });

        sink.add(1);
        sink.add(2);
        sink.add(3);
        sink.close();
      });

      test('转换错误事件', () {
        setUp();
        var transformer = StreamSinkTransformer.fromStreamTransformer(
            StreamTransformer.fromHandlers(handleError: (i, stackTrace, sink) {
              sink.addError((i as num) * 2, stackTrace);
            }));
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen((_) {},
            onError: (error, stackTrace) {
              results.add(error);
            }, onDone: () {
              expect(results);
            });

        sink.addError(1);
        sink.addError(2);
        sink.addError(3);
        sink.close();
      });

      test('转换已完成的事件', () {
        setUp();
        var transformer = StreamSinkTransformer.fromStreamTransformer(
            StreamTransformer.fromHandlers(handleDone: (sink) {
              sink.add(1);
              sink.close();
            }));
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen(results.add, onDone: () {
          expect(results);
        });

        sink.close();
      });

      test('从inner.close展望未来', () async {
        setUp();
        var transformer = StreamSinkTransformer.fromStreamTransformer(
            StreamTransformer.fromHandlers());
        var innerSink = CompleterStreamSink();
        var sink = transformer.bind(innerSink);

        var doneResult = ResultFuture(sink.done);
        doneResult.catchError((_) {});
        var closeResult = ResultFuture(sink.close());
        closeResult.catchError((_) {});
        await flushMicrotasks();
        expect(doneResult.isComplete);
        expect(closeResult.isComplete);

        innerSink.completer.complete();
        await flushMicrotasks();
        expect(doneResult.isComplete);
        expect(closeResult.isComplete);
      });

      test("从inner.close看不到未来", () async {
        setUp();
        var transformer = StreamSinkTransformer.fromStreamTransformer(
            StreamTransformer.fromHandlers(handleData: (_, sink) {
              sink.close();
            }));
        var innerSink = CompleterStreamSink();
        var sink = transformer.bind(innerSink);

        sink.add(1);
        innerSink.completer.completeError('oh no');
        await flushMicrotasks();

        expect(sink.done);
        expect(sink.close());
      });
    });

    group('StreamSinkTransformer.fromHandlers()', () {
      test('StreamSinkTransformer.fromHandlers() 转换数据事件', () {
        setUp();
        var transformer =
        StreamSinkTransformer.fromHandlers(handleData: (int i, sink) {
          sink.add(i * 2);
        });
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen(results.add, onDone: () {
          expect(results);
        });

        sink.add(1);
        sink.add(2);
        sink.add(3);
        sink.close();
      });

      test('转换错误事件', () {
        setUp();
        var transformer = StreamSinkTransformer.fromHandlers(
            handleError: (i, stackTrace, sink) {
              sink.addError((i as num) * 2, stackTrace);
            });
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen((_) {},
            onError: (error, stackTrace) {
              results.add(error);
            }, onDone: () {
              expect(results);
            });

        sink.addError(1);
        sink.addError(2);
        sink.addError(3);
        sink.close();
      });

      test('转换已完成的事件', () {
        setUp();
        var transformer = StreamSinkTransformer.fromHandlers(handleDone: (sink) {
          sink.add(1);
          sink.close();
        });
        var sink = transformer.bind(controller.sink);

        var results = [];
        controller.stream.listen(results.add, onDone: () {
          expect(results);
        });

        sink.close();
      });

      test('从inner.close展望未来', () async {
        setUp();
        var transformer = StreamSinkTransformer.fromHandlers();
        var innerSink = CompleterStreamSink();
        var sink = transformer.bind(innerSink);

        var doneResult = ResultFuture(sink.done);
        doneResult.catchError((_) {});
        var closeResult = ResultFuture(sink.close());
        closeResult.catchError((_) {});
        await flushMicrotasks();
        expect(doneResult.isComplete);
        expect(closeResult.isComplete);

        innerSink.completer.complete();
        await flushMicrotasks();
        expect(doneResult.isComplete);
        expect(closeResult.isComplete);
      });

      test("从inner.close看不到未来", () async {
        setUp();
        var transformer = StreamSinkTransformer.fromHandlers(handleData: (_, sink) {
          sink.close();
        });
        var innerSink = CompleterStreamSink();
        var sink = transformer.bind(innerSink);

        sink.add(1);
        innerSink.completer.completeError('oh no');
        await flushMicrotasks();

        expect(sink.done);
        expect(sink.close());
      });
    });
  }

}